<?php
class TestsService extends Service{

    /**
     * @param object $data
     * <pre>
     * {
     *   "type":"object",
     *   "properties": {
     *     "projectId":{"type":"integer"},
     *     "rows":{"type":"integer"},
     *     "page":{"type":"integer"},
     *     "sortField":{"type":"string"},
     *     "sortOrder":{"type":"string","enum":["asc","desc"]},
     *     "search":{"type":"array"}
     *   }
     * }
     * </pre>
     * @return array
     */
    public static function getAll($data) {
        if (self::_invoke()) return self::_output();
        $result = TestTable::findAllTestsArray(
            $data->projectId,
            $data->rows,
            $data->page,
            $data->sortField,
            $data->sortOrder,
            $data->search
        );
        $ar = array();
        $ar['page'] = $data->page;
        $ar['total'] = floor($result['numResults'] / $data->rows);
        $ar['records'] = $result['numResults'];
        $ar['rows'] = $result['items'];
        return $ar;
    }

    /**
     * @return array
     */
    public static function importTests() {
        if (self::_invoke()) return self::_output();
        $user = sfContext::getInstance()->getUser();
        if(!$user->getAttributeHolder()->has('projectId')) {
            throw new NoProjectSelectedException;
        }
        $projectId = $user->getAttribute('projectId');
        $project = ProjectsService::get($projectId);
        $dir = $project['tests_dir'];
        if(!file_exists($dir)) {
            throw new ServiceException('The directory "' . $dir . '", defined in this project settings, does not exists.');
        }
        $res = TestTable::importTests($dir, $projectId);
        $res['dir'] = $dir;
        return $res;
    }
    

    /**
     * @param string $dir
     * <pre>
     * {"type":"string"}
     * </pre>
     * @return array
     */
    public static function createDirTreeStructure($dir) {
        if (self::_invoke()) return self::_output();
        $idOffset = strlen($dir) + 1;
        $ar = array(
            'attributes'=>array('id'=>'node-root'),
            'data'=>'TESTS',
            'state'=>'open',
            'children'=>self::createChildren($dir,1,$idOffset)
        );
        return $ar;
    }

    protected static function createChildren($dir, $level, $idOffset) {
        static $n = 0;
        $it = new RecursiveDirectoryIterator($dir);
        $arAll = array();
        foreach($it as $file) {
            if(strpos($file,'.svn') !== false) continue;
            $ar = array(
                'attributes'=>array(
                    'id'=>'node-'.$n++,
                    'extra'=>json_encode(
                        array(
                            'filepath'=>substr($file->getRealPath(),$idOffset),
                            'isDir'=>$file->isDir(),
                            'filename'=>$file->getFilename()
                        )
                    )
                ),
                'data'=>$file->getFilename()
            );
            if($level < 2 ) {
                $ar['state'] = 'open';
            }
            if($file->isDir()) {
                $ar['dir'] = true;
                $ar['children'] = self::createChildren($file, $level+1, $idOffset);
            }
            $arAll[] = $ar;
        }
        return $arAll;
    }

    /**
     * @param object $data
     * <pre>
     * {
     *   "type":"object",
     *   "properties": {
     *     "projectId":{"type":"integer"},
     *     "existentClass":{"type":"boolean"},
     *     "className":{"type":"string"},
     *     "file":{"type":"string"},
     *     "dir":{"type":"string"},
     *     "methods":{"type":"string"}
     *   }
     * }
     * </pre>
     * @return int
     */
    public static function create($data) {
        if (self::_invoke()) return self::_output();
        if($data->existentClass) {
            $classname = basename(substr($data->file,1,-4));
            $pieces = explode(DIRECTORY_SEPARATOR, $data->file);
            $file = $pieces[1];
            $dir = $pieces[0];
        }
        else {
            $classname = self::adjustClassName($data->classname);
            $file = $classname.'.php';
            $dir = $data->file;
        }
        $firstSavedTestId = null;
        foreach( explode( "\n", $data->methods ) as $method) {
            $method = self::adjustMethodName($method);
            $test = new Test;
            $test->method = $method;
            $test->file = $file;
            $test->dir = $dir;
            $test->class = $classname;
            $test->project_id = $data->projectId;
            $test->save();
            if(!$firstSavedTestId) {
                $firstSavedTestId = $test->id;
            }
        }
        return $firstSavedTestId;
    }

    protected static function adjustMethodName($name) {
        $name = GraduaString::removeSpacesAndCapitalizeFirstLetters($name);
        if(strpos($name,'Test') === 0) {
            $name[0] = strtolower($name[0]);
        }
        else {
            $name = 'test'.$name;
        }
        return $name;
    }

    protected static function adjustClassName($name) {
        $name = GraduaString::removeSpacesAndCapitalizeFirstLetters($name);
        if(substr($name,-4) === '.php') {
            $name = substr($name,1,-4);
        }
        if(strpos($name,'Test') !== strlen($name)-4) {
            $name .= 'Test';
        }
        return $name;
    }

    
}
?>
